package com.firexxx.study.util.chart;

import com.firexxx.study.performancetest.scene.GridResult;
import com.firexxx.study.performancetest.scene.MultiResult;
import com.firexxx.study.performancetest.scene.SingleResult;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

import javax.swing.*;
import java.awt.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * TODO
 *
 * @author fireXXX
 * @date 2020/11/23 0:15
 **/
public class ChartUtil {

    public static void show(String title, SingleResult singleResult) {
        ChartFrame chartFrame = getChartFrame(singleResult);

        JFrame frame = new JFrame(title);
        frame.setLayout(new GridLayout(1, 1, 10, 10));
        frame.add(chartFrame.getChartPanel());

        frame.setPreferredSize(new Dimension(800, 600));
        frame.pack();
        frame.setVisible(true);
    }

    public static void show(String title, MultiResult multiResult) {
        multiResult.calMax();
        ChartFrame chartFrame = getChartFrame(multiResult);

        JFrame frame = new JFrame(title);
        frame.setLayout(new GridLayout(1, 1, 10, 10));
        frame.add(chartFrame.getChartPanel());

        frame.setPreferredSize(new Dimension(800, 600));
        frame.pack();
        frame.setVisible(true);
    }

    public static void show(String title, GridResult gridResult) {
        List<ChartFrame> chartFrames = getChartFrame(gridResult);

        JFrame frame = new JFrame(title);
        frame.setLayout(new GridLayout(gridResult.getData().size() / 2 + 1, 2, 10, 10));
        chartFrames.forEach(item -> frame.add(item.getChartPanel()));

        frame.setPreferredSize(new Dimension(800, 600));
        frame.pack();
        frame.setVisible(true);
    }

    public static ChartFrame getChartFrame(SingleResult result) {
        DefaultCategoryDataset mDataset = new DefaultCategoryDataset();

        String type = result.getName();
        List<Long> data = result.getData();

        for (int i = 0; i < data.size(); i++) {
            mDataset.addValue(data.get(i), type, String.valueOf(i + 1));
        }

        createTheme();
        JFreeChart mChart = ChartFactory.createLineChart(
                result.getName() + "性能测试",//图名字
                "时间",//横坐标
                "性能",//纵坐标
                mDataset,//数据集
                PlotOrientation.VERTICAL,
                true, // 显示图例
                true, // 采用标准生成器
                false);// 是否生成超链接
        //.LIGHT_GRAY
        CategoryPlot mPlot = (CategoryPlot) mChart.getPlot();
        setCategoryPlot(mPlot, result.getMax());

        return new ChartFrame(result.getName(), mChart);
    }

    public static ChartFrame getChartFrame(MultiResult result) {
        DefaultCategoryDataset mDataset = new DefaultCategoryDataset();

        List<SingleResult> list = result.getData();
        for (SingleResult singleResult : list) {
            String type = singleResult.getName();
            List<Long> data = singleResult.getData();

            for (int i = 0; i < data.size(); i++) {
                mDataset.addValue(data.get(i), type, String.valueOf(i + 1));
            }
        }

        createTheme();
        JFreeChart mChart = ChartFactory.createLineChart(
                result.getName() + "性能测试",//图名字
                "时间",//横坐标
                "性能",//纵坐标
                mDataset,//数据集
                PlotOrientation.VERTICAL,
                true, // 显示图例
                true, // 采用标准生成器
                false);// 是否生成超链接
        //.LIGHT_GRAY
        CategoryPlot mPlot = (CategoryPlot) mChart.getPlot();
        setCategoryPlot(mPlot, result.getMax());

        return new ChartFrame(result.getName(), mChart);
    }

    public static List<ChartFrame> getChartFrame(GridResult result) {
        List<ChartFrame> chartFrames = new ArrayList<>();

        List<SingleResult> list = result.getData();
        for (SingleResult singleResult : list) {
            chartFrames.add(getChartFrame(singleResult));
        }

        return chartFrames;
    }


    private static void createTheme() {
        StandardChartTheme mChartTheme = new StandardChartTheme("CN");
        mChartTheme.setLargeFont(new Font("黑体", Font.BOLD, 20));
        mChartTheme.setExtraLargeFont(new Font("宋体", Font.PLAIN, 15));
        mChartTheme.setRegularFont(new Font("宋体", Font.PLAIN, 15));
        ChartFactory.setChartTheme(mChartTheme);
    }

    private static void setCategoryPlot(CategoryPlot mPlot, long max) {
        mPlot.setBackgroundPaint(Color.white);
        mPlot.setRangeGridlinePaint(Color.BLUE);//背景底部横虚线
        mPlot.setOutlinePaint(Color.RED);//边界线

        /*
         * Y轴设置
         */
        NumberAxis vn = (NumberAxis) mPlot.getRangeAxis();
        DecimalFormat df = new DecimalFormat("#0.00");
        vn.setNumberFormatOverride(df); // 数据轴数据标签的显示格式
        vn.setUpperMargin(1);
        vn.setLowerMargin(1);
        vn.setAutoRangeMinimumSize(0.01);//最小跨度
        vn.setLowerBound(1);//最小值显示
        vn.setUpperBound(max);
        LineAndShapeRenderer lasp = (LineAndShapeRenderer) mPlot.getRenderer();// 获取显示线条的对象
        lasp.setBaseShapesVisible(true);// 设置拐点是否可见/是否显示拐点
        lasp.setDrawOutlines(true);// 设置拐点不同用不同的形状
        lasp.setUseFillPaint(true);// 设置线条是否被显示填充颜色
        lasp.setBaseFillPaint(Color.BLACK);//// 设置拐点颜色

        /*
         * X轴
         */
        CategoryAxis domainAxis = mPlot.getDomainAxis();
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
        domainAxis.setLowerMargin(-0.08);

        domainAxis.setCategoryMargin(0.5);
        ;

        domainAxis.setLabelFont(new Font("宋书", Font.PLAIN, 15)); // 设置横轴字体
        domainAxis.setTickLabelFont(new Font("宋书", Font.PLAIN, 15));// 设置坐标轴标尺值字体
        domainAxis.setLowerMargin(0.01);// 左边距 边框距离
        domainAxis.setUpperMargin(0.06);// 右边距 边框距离,防止最后边的一个数据靠近了坐标轴。
        domainAxis.setMaximumCategoryLabelLines(10);
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);// 横轴 lable 的位置 横轴上的 Lable 45度倾斜 DOWN_45
    }

}